#include "cammanager.h"

CamManager::CamManager(const QSize size) : cvimage(NULL), camera(NULL), inRefresh(false), imageSize(size)
{
    // Selection de la camera et de la resolution d'enregistrement
    camera = cvCaptureFromCAM(CV_CAP_ANY);
    cvSetCaptureProperty(camera, CV_CAP_PROP_FRAME_WIDTH, imageSize.width());
    cvSetCaptureProperty(camera, CV_CAP_PROP_FRAME_HEIGHT, imageSize.height());
    //Test de la camera
    if (!camera) {
        qDebug() << "Ouverture du flux vidéo impossible !";
    }
    // Initialisation de cvimage en recuperant une frame
    cvimage = cvQueryFrame(camera);
}

CamManager::~CamManager()
{
    if (camera){
        cvReleaseCapture(&camera);
        camera = NULL;
    }
    if (cvimage){
        cvReleaseImage(&cvimage);
        cvimage = NULL;
    }
}

void CamManager::run()
// Capte regulierement une frame de la camera et la distribue à tous les consommateurs
{
    refreshTime.start();

    timer = new QTimer();
    timer->moveToThread(QThread::currentThread());
    QObject::connect(timer, SIGNAL(timeout()), this, SLOT(refresh()), Qt::DirectConnection);
    connect(this, SIGNAL(stopSignal()), timer, SLOT(stop()), Qt::DirectConnection);
    timer->start(30);
    exec();
}

void CamManager::terminate()
// Surcharge de terminate pour arreter le thread proprement
{
    emit stopSignal();
}

void CamManager::refresh()
// Si un test est en cours, on affiche le temps de debut et la duree en plus de l'heure
{
    if(inRefresh){
        return;
    }
    inRefresh=true;
    refreshTime.restart();
    cvQueryFrame(camera);

    for(int i=0; i<cons.length(); i++){
        if(!cons.at(i)->setImage(cvimage))
        {
            busyConsList.append(i);
        }
    }

    long f(1000);
    while(!busyConsList.empty() && refreshTime.elapsed() < 28){
        for(QList<int>::iterator it = busyConsList.begin(); it != busyConsList.end(); )
        {
            if(cons.at(*it)->setImage(cvimage))
            {
                it = busyConsList.erase(it);
            }
            else
            {
                it++;
            }
        }
        usleep(f);
    }
    busyConsList.clear();
    inRefresh=false;
}

void CamManager::registerConsumer(ImageConsumer *const consumer)
// Enregistre un consommateur d'images qui recevra les frames de la camera
{
    cons.append(consumer);
}

void CamManager::removeConsumer(ImageConsumer *const consumer)
// Supprime un consommateur d'image
{
    cons.removeOne(consumer);
}
